#include  <windows.h>
#include  <iostream>
#include  <sstream>
using namespace std;

LPBYTE ResaveFile(LPBYTE lpbMapAddress,DWORD dwBlockSize,LPCSTR lpszSaveName){
	HANDLE hFile = CreateFile(lpszSaveName,GENERIC_WRITE|GENERIC_READ,
		FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
	if(!hFile){
		cout<<"Create Destination File failed"<<endl;
		return 0;
	}
	WriteFile(hFile,lpbMapAddress,dwBlockSize,NULL,NULL);
	CloseHandle(hFile);
	return lpbMapAddress + dwBlockSize;
}

int main(int argc,char *argv[])
{
	int nSplitNum;
	if(argc < 3){
		cout<<"The Syntax of command is error."<<endl;
		return 0;
	}
	nSplitNum = atoi(argv[2]);
	string strSourceFile(argv[1]);
	cout<<"Start resaving"<<endl;
   	HANDLE hFile = CreateFile(strSourceFile.c_str(),GENERIC_READ|GENERIC_WRITE,
	   FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
	HANDLE hMapFile = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
	if(!hMapFile){
		cout<<"Create Map File failed"<<endl;
		return 0;
	}
	SYSTEM_INFO SysInfo;
	GetSystemInfo(&SysInfo);
	DWORD dwGran = SysInfo.dwAllocationGranularity;
	cout<<"Granularity: "<<dwGran<<endl;
	DWORD dwFileSizeHigh;
	__int64 qwFileSize = GetFileSize(hFile,&dwFileSizeHigh);
	qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
	CloseHandle(hFile);
	cout<<"File size: "<<qwFileSize<<" Bytes"<<endl;
	__int64 qwFileOffset = 0;
	DWORD dwByteInBlock = (qwFileSize/dwGran/nSplitNum + 1) * dwGran;
	cout<<"Block size:"<<dwByteInBlock<<endl<<"Working..."<<endl;
	
	for(int nCount = 0;nCount < nSplitNum && qwFileOffset < qwFileSize	;++nCount){
		if(qwFileSize - qwFileOffset < dwByteInBlock)
			dwByteInBlock = (DWORD)(qwFileSize - qwFileOffset);
			
		LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(hMapFile,FILE_MAP_READ,(DWORD)(qwFileOffset >> 32),(DWORD)(qwFileOffset & 0xFFFFFFFF),dwByteInBlock);
		if(!lpbMapAddress){
			cerr<<"Map View created failed."<<endl;
			DWORD ErrorCode = 0;
			if((ErrorCode = GetLastError()) == ERROR_NOT_ENOUGH_MEMORY || ErrorCode == ERROR_INVALID_PARAMETER)
				cout<<"Error "<<ErrorCode<<" : ERROR_NOT_ENOUGH_MEMORY"<<endl;
			return 0;
		}
		ostringstream ostr;
		ostr<<strSourceFile<<".split.part"<<nCount + 1;
		ResaveFile(lpbMapAddress,dwByteInBlock,ostr.str().c_str());
		qwFileOffset += dwByteInBlock;
		cout<<dwByteInBlock<<" bytes Writen. Working..."<<endl;
		UnmapViewOfFile(lpbMapAddress);
	}
	CloseHandle(hMapFile);
	return 0;
}
